package com.schedule;

import com.alibaba.fastjson.JSONObject;
import com.schedule.domain.ReportRule;
import com.schedule.domain.ReportRuleTask;
import com.schedule.domain.Template;
import com.schedule.jobs.ReportJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

@Slf4j
@Service
public class ReportGenerateScheduleManage {

    public final static String PARAM_KEY_RULE = "RULE_PARAM";
    public final static String PARAM_KEY_RULE_TASK = "RULE_TASK_PARAM";

    String jobGroup = "REPORT_GROUP";

    final static Set<String> JOB_CACHE = new ConcurrentSkipListSet<>();

    @Autowired
    private Scheduler scheduler;

    /**
     * 保存定时任务
     */
    @SuppressWarnings("unchecked")
    public void addJob(Template template, List<ReportRuleTask> reportRuleTasks) {
        String interval = template.getCron();
        // 使用资源、协议、调度时间组合成jobName
        String jobName = template.getId(),
                jobDescription = "task interval:"+interval,
                createTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        try {

            log.info("设置触发器Key！");
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

            log.info("设置任务Key！");
            JobKey jobKey = JobKey.jobKey(jobName, jobGroup);

            log.info("生成Crontab调度器！");
            CronScheduleBuilder schedBuilder = CronScheduleBuilder
                    .cronSchedule(interval)
                    .withMisfireHandlingInstructionDoNothing();


            log.info("生成Crontab触发器！");
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerKey)
                    .withDescription(createTime)
                    .withSchedule(schedBuilder).build();

            log.info("生成JOB执行器！");


            JobDetail jobDetail = JobBuilder.newJob(ReportJob.class)
                    .withIdentity(jobKey)
                    .withDescription(jobDescription)
                    .usingJobData(PARAM_KEY_RULE, JSONObject.toJSONString(template))
//                    .usingJobData(PARAM_KEY_RULE_TASK, JSONObject.toJSONString(reportRuleTasks))
                    .build();

            log.info("添加到任务调度表！");
            scheduler.scheduleJob(jobDetail, trigger);
            log.info("添加到任务调度表成功！");
        } catch (SchedulerException e) {
            log.info("添加到任务调度表失败！");
            e.printStackTrace();
        }finally {
            JOB_CACHE.add(template.getId());
        }
    }


    /**
     * 修改定时任务
     * @param template
     * @param reportRuleTasks
     */
    public void edit(Template template, List<ReportRuleTask> reportRuleTasks) {

        try {
            if(JOB_CACHE.contains(template.getId())){
                // 将从触发器中删除该任务
                delete(template, reportRuleTasks);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }

            // 将调度重新加入到调度中去
            addJob(template, reportRuleTasks);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("类名不存在或执行表达式错误");
        }
    }

    /**
     * 删除定时任务
     *
     */
    public void delete(Template reportRule, List<ReportRuleTask> reportRuleTasks){
        
        try {
            log.info("将删除任务,任务ID:{}",reportRule.getId());
            log.info("将删除任务：{}", JSONObject.toJSONString(reportRule));

            if (JOB_CACHE.contains(reportRule.getId())) {

                String jobName = reportRule.getId();
                log.info("获取原任务所在触发器，触发器ID:",jobName);
                TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

                log.info("调度器中将会移除该触发器!");
                scheduler.pauseTrigger(triggerKey);
                log.info("暂停触发器!");
                boolean rst = scheduler.unscheduleJob(triggerKey);
                log.info("卸载触发器，卸载结果:{}",rst);
                boolean removeStatus = JOB_CACHE.remove(reportRule.getId());
                log.info("移除任务,移除结果:{}",(removeStatus?"失败！":"成功！"));
                log.info("删除完成", triggerKey);

                //20181017|张绚|删除配置信息
                log.info("配置信息删除成功,任务ID:{}", reportRule.getId());
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("任务删除时发生错误!",e);
        }
    }

}
